#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include "summary.h"
#include <string.h>
#include <tr1/unordered_set>
#include <time.h>

//#define NUMINTS  262144
//zipf_16000000_2.25.bin

using namespace std;
using namespace tr1;

void do_mmap(char * argv[]) {
	//StreamSummaryBucket hs(800);

	unordered_set<int> count;
	struct stat sb;
	string DIR = "../../data/";
	string FILENAME = argv[1];
	int m = atoi(argv[2]);


	FILENAME = DIR + FILENAME;
	const char * FILEPATH = FILENAME.c_str();
	cerr << "do_mmap" << endl;

	//printf("Staring filesize: %f\n ", FILESIZE);

	int fd = open(FILEPATH, O_RDONLY);
	int * iptr;
	float * fptr;
	int FILESIZE;

	if (fd == -1) {
		perror("Error opening file for reading");
		exit (EXIT_FAILURE);
	}

	if (fstat(fd, &sb) == -1) {
		perror("Error on fstat");
		exit (EXIT_FAILURE);
	}

	for (int k = 1; k < 2; k++) {
		size_t time = 0;
		StreamSummaryBucket hs(k*m);
		for (int i = 0; i < 1; i++) {
			FILESIZE = sb.st_size / (sizeof(int) + sizeof(float));
			char * map = (char *) mmap(0, sb.st_size, PROT_READ, MAP_SHARED, fd, 0);
			if (map == MAP_FAILED) {
				close(fd);
				perror("Error mmapping the file");
				exit (EXIT_FAILURE);
			}
			clock_t start = clock();
			iptr = (int*) map;
			for (int i = 0; i < FILESIZE; i++) {
				fptr = (float*) (iptr + 1);
				//cerr << iptr[0] << "," << fptr[0] << endl;
				if (count.find(iptr[0]) == count.end())
				count.insert(iptr[0]);
				hs.insert(iptr[0], iptr[0], fptr[0]);
				//cerr << hs.to_string() << endl << endl;
				//hs.checksummary();
				iptr = (int*) (iptr + 2);
			}

			clock_t ends = clock();

			if (munmap(map, sb.st_size) == -1) {
				perror("Error un-mmapping the file");
			}

			time += ends - start;

		}
		//cout << k * m << "\t"<<  (double) (time) / (3* CLOCKS_PER_SEC) << endl;
	}

	close(fd);

	//printf("finished SUM size: %d\n ", hs.summarysize());
	//printf("Uniques: %d\n ", count.size());
	//cerr << "Running Time : " << (double) (ends - start) / CLOCKS_PER_SEC

	//cerr << hs.to_string() << endl;
}

int main(int argc, char *argv[]) {
	do_mmap(argv);
	return 0;
}
